struct CPU {
    position_in_memory: usize, //内存位置，程序计数器
    registers: [u8; 16],       //16个寄存器
    memory: [u8; 0x1000],      //4k内存
}
impl CPU {
    //如果从内存读会很复杂
    fn read_opcode(&self) -> u16 {
        let p = self.position_in_memory;
        let op_byte1 = self.memory[p] as u16;
        let op_byte2 = self.memory[p + 1] as u16;
        op_byte1 << 8 | op_byte2 //先转换为U16,防止移位后高位为0，再拼接
    }

    fn run(&mut self) {
        loop {
            let opcode = self.read_opcode();
            self.position_in_memory += 2; //自增程序计数，指向下一条指令

            let c = ((opcode & 0xF000) >> 12) as u8;
            let x = ((opcode & 0x0F00) >> 8) as u8;
            let y = ((opcode & 0x00F0) >> 4) as u8;
            let d = ((opcode & 0x000F) >> 0) as u8;

            match (c, x, y, d) {
                (0, 0, 0, 0) => {
                    return; //遇到操作码0x0000时，此处短路功能终止函数执行
                }
                (0x8, _, _, 0x4) => self.add_xy(x, y), //匹配元组，分配到“硬件电路”
                _ => todo!("opcode{:04x}", opcode),    //需要补充
            }
        }
    }

    fn add_xy(&mut self, x: u8, y: u8) {
        let arg1 = self.registers[x as usize];
        let arg2 = self.registers[y as usize];

        let (val, overflow) = arg1.overflowing_add(arg2); //如果溢出，返回的bool为true
        self.registers[x as usize] = val;

        if overflow {
            self.registers[0xF] = 1;
        } else {
            self.registers[0xF] = 0;
        }
    }
}
fn main() {
    let mut cpu = CPU {
        registers: [0; 16],
        memory: [0; 4096],
        position_in_memory: 0,
    };

    //初始化寄存器

    cpu.registers[0] = 5;
    cpu.registers[1] = 10;
    cpu.registers[2] = 10;
    cpu.registers[3] = 10;

    let mem = &mut cpu.memory;
    mem[0] = 0x80;
    mem[1] = 0x14; //0x8014 把寄存器1的值加到寄存器0上
    mem[2] = 0x80;
    mem[3] = 0x24; //0x8024 把寄存器2的值加到寄存器0上
    mem[4] = 0x80;
    mem[5] = 0x34; //0x8034 把寄存器3的值加到寄存器0上
    cpu.run();

    assert_eq!(cpu.registers[0], 35);
    println!("5 + 10 +10 +10 = {}", cpu.registers[0]);
}
